package com.redepronik.negosysres.invfac.report;

import static com.redepronik.negosys.utils.Utils.compareTo;
import static com.redepronik.negosys.utils.Utils.comprobarCedula;
import static com.redepronik.negosys.utils.Utils.diasMora;
import static com.redepronik.negosys.utils.Utils.fechaFormatoString;
import static com.redepronik.negosys.utils.Utils.moraTotal;
import static com.redepronik.negosys.utils.Utils.multiplicarDivide;
import static com.redepronik.negosys.utils.Utils.newBigDecimal;
import static com.redepronik.negosys.utils.Utils.redondear;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.event.ActionEvent;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.redepronik.negosys.invfac.entity.Detallecredito;
import com.redepronik.negosys.invfac.entity.Egreso;
import com.redepronik.negosys.invfac.entityAux.CentralRiesgoReporte;
import com.redepronik.negosys.invfac.entityAux.CobranzaReporte;
import com.redepronik.negosys.invfac.entityAux.CobranzaReporteAuxiliar;
import com.redepronik.negosys.invfac.service.EgresoService;
import com.redepronik.negosys.invfac.service.MoraService;
import com.redepronik.negosys.rrhh.entity.Ciudad;
import com.redepronik.negosys.rrhh.entity.Persona;
import com.redepronik.negosys.rrhh.entity.Provincia;
import com.redepronik.negosys.rrhh.service.CiudadService;
import com.redepronik.negosys.rrhh.service.ClienteService;
import com.redepronik.negosys.rrhh.service.PersonaService;
import com.redepronik.negosys.rrhh.service.ProvinciaService;
import com.redepronik.negosys.utils.service.ReporteService;

@Controller
@Scope("session")
public class CreditoReport {

	@Autowired
	private ReporteService reporteService;

	@Autowired
	private PersonaService personaService;

	@Autowired
	private ClienteService clienteService;

	@Autowired
	private EgresoService egresoService;

	@Autowired
	private ProvinciaService provinciaService;

	@Autowired
	private CiudadService ciudadService;

	@Autowired
	private MoraService moraService;

	private List<Provincia> listaProvincias;
	private List<Ciudad> listaCiudades;

	private Provincia provincia;
	private Ciudad ciudad;

	public CreditoReport() {
		ciudad = new Ciudad();
		provincia = new Provincia();
		listaCiudades = new ArrayList<Ciudad>();
	}

	public void cargarCiudades() {
		if (provincia.getProvinciaid() != 0) {
			listaCiudades = new ArrayList<Ciudad>();
			listaCiudades = ciudadService.obtenerPorProvincia(provincia);
		}
	}

	private String comprobarCed(String cedulaRuc) {
		if (comprobarCedula(cedulaRuc)) {
			if (cedulaRuc.length() == 10)
				return "C";
			else if (cedulaRuc.length() == 13)
				return "R";
		}
		return "NO TIENE";
	}

	private int diasVencido(Date fechaCorte, Egreso egreso) {
		List<Detallecredito> list2 = egreso.getCredito().getDetallecreditos();
		for (Detallecredito detalleCredito : list2)
			if (!detalleCredito.getPagado())
				if (detalleCredito.getFechalimite().compareTo(fechaCorte) < 0)
					return diasMora(fechaCorte, detalleCredito.getFechalimite())
							.intValue();

		return 0;
	}

	@SuppressWarnings("static-access")
	private Date fechaCorte() {
		Calendar cal = Calendar.getInstance();
		int anio = cal.get(Calendar.YEAR);
		int mes = cal.get(Calendar.MONTH);
		int dia = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
		if (mes == 0) {
			mes = 11;
			anio--;
		} else {
			mes--;
			cal.set(anio, mes, Calendar.DAY_OF_MONTH);
			dia = cal.getActualMaximum(cal.DAY_OF_MONTH);
		}
		cal.set(anio, mes, dia);
		return cal.getTime();
	}

	private List<CentralRiesgoReporte> generarCentralRiesgo() {
		Date FEC_CORTE_SALDO = fechaCorte();
		List<CentralRiesgoReporte> list = new ArrayList<CentralRiesgoReporte>();

		List<Egreso> listaEgreso = egresoService
				.obtenerPorCreditoAlDiaAndFechaLimite(FEC_CORTE_SALDO);

		List<Egreso> listaEgresoVencido = egresoService
				.obtenerPorCreditoVencidoAndFechaLimite(FEC_CORTE_SALDO);

		if (listaEgreso != null && !listaEgreso.isEmpty()) {

			for (int i = 0; i < listaEgreso.size(); i++)
				for (Detallecredito detalleCredito : listaEgreso.get(i)
						.getCredito().getDetallecreditos())
					if (detalleCredito.getFechalimite().compareTo(
							FEC_CORTE_SALDO) > 0) {
						listaEgreso.remove(i);
						break;
					}

			int morososEnviar = listaEgreso.size() * 28 / 72;
			for (int i = 0; i <= morososEnviar; i++)
				listaEgreso.add(listaEgresoVencido.get(i));

			for (Egreso egreso : listaEgreso) {
				if (egreso.getPagado() == false) {
					CentralRiesgoReporte centralRiesgoReporteCliente = new CentralRiesgoReporte();
					Persona cliente = personaService.obtenerPorPersonaId(egreso
							.getClienteFactura().getPersona().getPersonaid());

					String VAL_OPERACION = totalFactura(egreso);
					String VAL_TOTAL = totalTotal(egreso, FEC_CORTE_SALDO);
					String VAL_VENCIDO = totalVencido(egreso, FEC_CORTE_SALDO);
					String VAL_XVENCER = totalXVencer(egreso, FEC_CORTE_SALDO);
					int NUM_DIAS_VENCIDO = diasVencido(FEC_CORTE_SALDO, egreso);

					centralRiesgoReporteCliente
							.setCOD_TIPO_ID(comprobarCed(cliente.getCedula()));
					centralRiesgoReporteCliente.setCOD_ID_SUJETO(cliente
							.getCedula());
					centralRiesgoReporteCliente.setNOM_SUJETO(cliente
							.getNombre() + " " + cliente.getApellido());
					centralRiesgoReporteCliente.setDIRECCION(cliente
							.getDireccion());
					centralRiesgoReporteCliente.setCIUDAD(cliente.getCiudad()
							.getNombre());
					if (!cliente.getTelefonopersonas().isEmpty())
						centralRiesgoReporteCliente.setTELEFONO(cliente
								.getTelefonopersonas().get(0).getTelefono());
					else
						centralRiesgoReporteCliente.setTELEFONO("0994387691");

					// //////////////////////////////
					centralRiesgoReporteCliente.setACREEDOR("ALMACENES PATTY");
					centralRiesgoReporteCliente
							.setFEC_CORTE_SALDO(fechaFormatoString(FEC_CORTE_SALDO));
					centralRiesgoReporteCliente.setTIPO_DEUDOR("TITULAR");
					centralRiesgoReporteCliente.setNUM_OPERACION(String
							.valueOf(egreso.getEgresoid()));
					centralRiesgoReporteCliente
							.setFEC_CONCESION(fechaFormatoString(egreso
									.getFechainicio()));
					centralRiesgoReporteCliente.setVAL_OPERACION(VAL_OPERACION);
					centralRiesgoReporteCliente.setVAL_TOTAL(VAL_TOTAL);
					centralRiesgoReporteCliente.setVAL_XVENCER(VAL_XVENCER);
					centralRiesgoReporteCliente.setVAL_VENCIDO(VAL_VENCIDO);
					centralRiesgoReporteCliente.setVAL_DEM_JUDICIAL("0,00");
					centralRiesgoReporteCliente.setVAL_CART_CASTIGADA("0,00");
					centralRiesgoReporteCliente
							.setNUM_DIAS_VENCIDO(NUM_DIAS_VENCIDO);

					list.add(centralRiesgoReporteCliente);

					List<Persona> listGarantes = clienteService
							.obtenerGarantesPorCredito(egreso.getCredito()
									.getCreditoid());
					if (!listGarantes.isEmpty()) {
						CentralRiesgoReporte centralRiesgoReporteGarante = new CentralRiesgoReporte();
						Persona garante = listGarantes.get(0);

						centralRiesgoReporteGarante
								.setCOD_TIPO_ID(comprobarCed(garante
										.getCedula()));
						centralRiesgoReporteGarante.setCOD_ID_SUJETO(garante
								.getCedula());
						centralRiesgoReporteGarante.setNOM_SUJETO(garante
								.getNombre() + " " + garante.getApellido());
						centralRiesgoReporteGarante.setDIRECCION(garante
								.getDireccion());
						centralRiesgoReporteGarante.setCIUDAD(garante
								.getCiudad().getNombre());
						if (!garante.getTelefonopersonas().isEmpty()) {
							centralRiesgoReporteGarante
									.setTELEFONO(garante.getTelefonopersonas()
											.get(0).getTelefono());
							if (list.get(
									list.indexOf(centralRiesgoReporteCliente))
									.getTELEFONO()
									.equalsIgnoreCase("0994387691"))
								list.get(
										list.indexOf(centralRiesgoReporteCliente))
										.setTELEFONO(
												garante.getTelefonopersonas()
														.get(0).getTelefono());
						} else
							centralRiesgoReporteGarante
									.setTELEFONO("0994387691");

						// //////////////////////////////
						centralRiesgoReporteGarante
								.setACREEDOR("ALMACENES PATTY");
						centralRiesgoReporteGarante
								.setFEC_CORTE_SALDO(fechaFormatoString(FEC_CORTE_SALDO));
						centralRiesgoReporteGarante.setTIPO_DEUDOR("GARANTE");
						centralRiesgoReporteGarante.setNUM_OPERACION(String
								.valueOf(egreso.getEgresoid()));
						centralRiesgoReporteGarante
								.setFEC_CONCESION(fechaFormatoString(egreso
										.getFechainicio()));
						centralRiesgoReporteGarante
								.setVAL_OPERACION(VAL_OPERACION);
						centralRiesgoReporteGarante.setVAL_TOTAL(VAL_TOTAL);
						centralRiesgoReporteGarante.setVAL_XVENCER(VAL_XVENCER);
						centralRiesgoReporteGarante.setVAL_VENCIDO(VAL_VENCIDO);
						centralRiesgoReporteGarante.setVAL_DEM_JUDICIAL("0,00");
						centralRiesgoReporteGarante
								.setVAL_CART_CASTIGADA("0,00");
						centralRiesgoReporteGarante
								.setNUM_DIAS_VENCIDO(NUM_DIAS_VENCIDO);

						list.add(centralRiesgoReporteGarante);
					}

				}
			}
		}
		return list;
	}

	private List<CobranzaReporte> generarCobranza() {
		List<CobranzaReporte> list = new ArrayList<CobranzaReporte>();
		List<Egreso> listaEgreso = egresoService
				.obtenerNoPagadosPorCiudad(ciudad.getCiudadid());
		for (Egreso egreso : listaEgreso) {
			CobranzaReporte cobranzaReporte = new CobranzaReporte();
			cobranzaReporte.setCliente(personaService
					.obtenerPorPersonaId(egreso.getCliente().getPersona()
							.getPersonaid()));
			List<Persona> listaGarantes = clienteService
					.obtenerGarantesPorCredito(egreso.getCredito()
							.getCreditoid());
			if (listaGarantes != null && !listaGarantes.isEmpty())
				cobranzaReporte.setGarante(personaService
						.obtenerPorPersonaId(listaGarantes.get(0)
								.getPersonaid()));

			if (!egreso.getDetalleegresos().isEmpty())
				cobranzaReporte.setNombreProducto(egreso.getDetalleegresos()
						.get(0).getProducto().getNombre());

			cobranzaReporte.setList(new ArrayList<CobranzaReporteAuxiliar>());
			BigDecimal mora = moraService.obtenerPorFecha(
					egreso.getFechainicio()).getPorcentaje();
			BigDecimal total = new BigDecimal("0");
			for (Detallecredito detalleCredito : egreso.getCredito()
					.getDetallecreditos()) {
				if (!detalleCredito.getPagado()) {
					CobranzaReporteAuxiliar cobranzaReporteAuxiliar = new CobranzaReporteAuxiliar();
					if (compareTo(detalleCredito.getFechalimite(), new Date()) < 0) {
						if (compareTo(new Date(), detalleCredito.getFechamora()) >= 0) {
							BigDecimal moraTotal = moraTotal(new Date(),
									detalleCredito.getFechamora(), mora);
							cobranzaReporteAuxiliar.setMora(multiplicarDivide(
									moraTotal, detalleCredito.getSaldo()));
							cobranzaReporteAuxiliar
									.setSubTotal(redondear(detalleCredito
											.getSaldo().add(
													cobranzaReporteAuxiliar
															.getMora())));
						} else {
							cobranzaReporteAuxiliar.setMora(newBigDecimal());
							cobranzaReporteAuxiliar
									.setSubTotal(redondear(detalleCredito
											.getSaldo()));
						}
						total = total
								.add(cobranzaReporteAuxiliar.getSubTotal());

						cobranzaReporteAuxiliar
								.setFechaLimite(fechaFormatoString(detalleCredito
										.getFechalimite()));

						cobranzaReporteAuxiliar
								.setSaldo(redondear(detalleCredito.getSaldo()));
						cobranzaReporte.getList().add(cobranzaReporteAuxiliar);
					}
				}
			}
			cobranzaReporte.setTotal(redondear(total));
			list.add(cobranzaReporte);
		}

		return list;
	}

	public Ciudad getCiudad() {
		return ciudad;
	}

	public List<Ciudad> getListaCiudades() {
		return listaCiudades;
	}

	public List<Provincia> getListaProvincias() {
		return listaProvincias;
	}

	public Provincia getProvincia() {
		return provincia;
	}

	@PostConstruct
	public void init() {
		listaProvincias = provinciaService.obtener();
	}

	public void reporteCentralRiesgo(ActionEvent actionEvent) {
		List<CentralRiesgoReporte> list = generarCentralRiesgo();
		Map<String, Object> parametro = new HashMap<String, Object>();
		reporteService.generarReporteXLS(list, parametro, "DATOS");
	}

	public void reporteCobranza(ActionEvent actionEvent) {
		List<CobranzaReporte> list = generarCobranza();
		Map<String, Object> parametro = new HashMap<String, Object>();
		parametro.put("CIUDAD",
				ciudadService.obtenerPorCiudadId(ciudad.getCiudadid())
						.getNombre());
		reporteService.generarReportePDF(list, parametro, "CobranzaCredito");
	}

	public void setCiudad(Ciudad ciudad) {
		this.ciudad = ciudad;
	}

	public void setListaCiudades(List<Ciudad> listaCiudades) {
		this.listaCiudades = listaCiudades;
	}

	public void setListaProvincias(List<Provincia> listaProvincias) {
		this.listaProvincias = listaProvincias;
	}

	public void setProvincia(Provincia provincia) {
		this.provincia = provincia;
	}

	private String totalFactura(Egreso egreso) {
		return redondear(egreso.getCredito().getMonto()).toString().replace(
				'.', ',');
	}

	private String totalTotal(Egreso egreso, Date fechaCorte) {
		BigDecimal val = newBigDecimal();
		for (Detallecredito detalleCredito : egreso.getCredito()
				.getDetallecreditos())
			if (!detalleCredito.getPagado())
				val = val.add(detalleCredito.getCuota());
		return redondear(val).toString().replace('.', ',');
	}

	private String totalVencido(Egreso egreso, Date fechaCorte) {
		BigDecimal val = newBigDecimal();
		for (Detallecredito detalleCredito : egreso.getCredito()
				.getDetallecreditos())
			if (!detalleCredito.getPagado())
				if (compareTo(detalleCredito.getFechalimite(), fechaCorte) < 0)
					val = val.add(detalleCredito.getCuota());
		return redondear(val).toString().replace('.', ',');
	}

	private String totalXVencer(Egreso egreso, Date fechaCorte) {
		BigDecimal val = newBigDecimal();
		for (Detallecredito detalleCredito : egreso.getCredito()
				.getDetallecreditos())
			if (!detalleCredito.getPagado())
				if (compareTo(detalleCredito.getFechalimite(), fechaCorte) >= 0)
					val = val.add(detalleCredito.getCuota());
		return redondear(val).toString().replace('.', ',');
	}

}